package com.sojson.util.lock;

import java.util.concurrent.TimeUnit;

import com.sojson.constant.Constant;
import com.sojson.constant.ConstantByMap;
import com.sojson.util.lock.impl.DistributedLockRedissonUtilImpl;
import com.sojson.util.lock.impl.ThisLockReentrantLockUtilImpl;
import com.sojson.util.properties.PropertiesUtil;
import com.sojson.util.text.Convert;

/**
 * 分布式锁工具类
 * 
 * @author liu
 * @date 2020-11-15
 */
public class LockUtil {

    /** 锁缓存持久化的时候为了和其他属性区分加的前缀,不设置为Lock */
    public static final String CACHE_NAME_PREFIX_LOCK = ConstantByMap.CACHE_NAME_PREFIX
        + Convert.toStr(Constant.PROPERTIES.getProperty("so.cache.name.prefix.lock"), "Lock");
    /** 获取锁的超时时间(单位: 秒,不设置为10秒) */
    public static final Integer TIMEOUT_GET =
        Convert.toInt(PropertiesUtil.getNumberFormat(Constant.PROPERTIES.getProperty("so.lock.timeout.get")), 10);
    /** 使用锁的超时时间(单位: 秒,不设置为30秒) */
    public static final Integer TIMEOUT_USE =
        Convert.toInt(PropertiesUtil.getNumberFormat(Constant.PROPERTIES.getProperty("so.lock.timeout.use")), 30);
    /** 使用锁的超时时间(单位: 毫秒,不设置为30秒) */
    public static final Integer TIMEOUT_USE_MILLIS = TIMEOUT_USE * 1000;
    /** 锁的超时时间单位 */
    public static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
    /** 超时时间(永久) */
    public static final int TIMEOUT_LONG = -1;
    private static final DistributedLockUtilInterface DISTRIBUTED_LOCK_UTIL_INTERFACE =
        ThisLockReentrantLockUtilImpl.getInstances();
    private static final DistributedLockUtilInterface LOCK_REDIS = DistributedLockRedissonUtilImpl.getInstances();

    /**
     * 获取锁
     * 
     * @param lockName 锁名称
     * @return
     */
    public static CustomLock getLock(String lockName) {
        return DISTRIBUTED_LOCK_UTIL_INTERFACE.getLock(lockName);
    }

    /**
     * 获取Redis锁
     * 
     * @param lockName 锁名称
     * @return
     */
    public static CustomLock getLockRedis(String lockName) {
        return LOCK_REDIS.getLock(lockName);
    }

    /**
     * 获取默认锁(有获取锁的超时时间,有使用锁的超时时间)
     * 
     * @param lockName  锁名称
     * @return
     * @throws Exception 
     */
    public static CustomLock defaultLock(String lockName) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.defaultLock();
        return lock;
    }

    /**
     * 获取默认锁
     * 
     * @param lockName      锁名称
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @return
     * @throws Exception 
     */
    public static CustomLock defaultLock(String lockName, long timeOutUse) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.defaultLock(timeOutUse);
        return lock;
    }

    /**
     * 获取默认锁
     * 
     * @param lockName      锁名称
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @param unit          使用锁的超时时间单位
     * @return
     * @throws Exception 
     */
    public static CustomLock defaultLock(String lockName, long timeOutUse, TimeUnit unit) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.defaultLock(timeOutUse, unit);
        return lock;
    }

    /**
     * 上锁,如果获取到就结束,没有获取到就一直暂停直到抛异常或者程序结束
     * 
     * @param lockName 锁名称
     * @return
     * @throws Exception 
     */
    public static CustomLock lock(String lockName) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.lock();
        return lock;
    }

    /**
     * 上锁,如果获取到返回true,没有获取到返回false
     * 
     * @param lockName 锁名称
     * @return
     * @throws Exception 
     */
    public static CustomLock tryLock(String lockName) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.tryLock();
        return lock;
    }

    /**
     * 在给定的时间内上锁,如果获取到返回true,超时或者没有获取到返回false
     * 
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @return
     * @throws Exception 
     */
    public static CustomLock tryLock(String lockName, long timeOutGet) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.tryLock(timeOutGet);
        return lock;
    }

    /**
     * 在给定的时间内上锁,如果获取到返回true,超时或者没有获取到返回false
     * 
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(不设置为10秒)
     * @param unit          获取锁的超时时间单位
     * @return
     * @throws Exception 
     */
    public static CustomLock tryLock(String lockName, long timeOutGet, TimeUnit unit) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.tryLock(timeOutGet, unit);
        return lock;
    }

    /**
     * 在给定的时间内获取锁,如果获取到返回true,超时或者没有获取到返回false
     * 
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @return
     * @throws Exception 
     */
    public static CustomLock lock(String lockName, long timeOutGet, long timeOutUse) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.lock(timeOutGet, timeOutUse);
        return lock;
    }

    /**
     * 在给定的时间内获取锁,如果获取到返回true,超时或者没有获取到返回false
     * 
     * @param lockName      锁名称
     * @param timeOutGet    获取锁的超时时间(单位: 秒,不设置为10秒)
     * @param timeOutUse    使用锁的超时时间(单位: 秒,不设置为30秒)
     * @param unit          锁的超时时间单位
     * @return
     * @throws Exception 
     */
    public static CustomLock lock(String lockName, long timeOutGet, long timeOutUse, TimeUnit unit) throws Exception {
        CustomLock lock = getLock(lockName);
        lock.lock(timeOutGet, timeOutUse, unit);
        return lock;
    }

    /**
     * 
     * 
     * @throws InterruptedException
     */
    public static CustomLock lockInterruptibly(String lockName) throws InterruptedException {
        CustomLock lock = getLock(lockName);
        lock.lockInterruptibly();
        return lock;
    }

}